package org.study4j.message.mq.rabbitmq.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.core.RabbitTemplate.ConfirmCallback;
import org.springframework.amqp.rabbit.core.RabbitTemplate.ReturnCallback;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;

/**
 * @description rabbitmq中间件配置
 * @author jiangbin
 * @date 2019年1月20日 下午9:14:55
 * @version 1.0.0
 */
@Configuration
@Slf4j
public class RabbitMQConfig {
	@Resource
	private CachingConnectionFactory connectionFactory;

	@Bean
	public SimpleMessageListenerContainer messageContainer() {
		SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
		// 设置确认模式为手动确认
		container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
		return container;
	}

	@Bean
	public RabbitTemplate rabbitTemplate() {
		// 被注释的代码表示已经在配置文件application.properties实现，无需重复设置
		// connectionFactory.setPublisherConfirms(true);
		// connectionFactory.setPublisherReturns(true);
		RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
		// rabbitTemplate.setMandatory(true);

		log.info("MQ的ConnectionFactory配置信息：{}", connectionFactory);
		// 设置消息发送成功的回调方法
		rabbitTemplate.setConfirmCallback(new ConfirmCallback() {
			@Override
			public void confirm(CorrelationData correlationData, boolean ack, String cause) {
				if(ack) {
					log.info("消息发送成功:correlationData({}),ack({}),cause({})", correlationData, ack, cause);
				}else {
					log.info("消息发送失败:correlationData({}),ack({}),cause({})", correlationData, ack, cause);
				}
			}
		});

		// 设置消息分发失败的的回调方法
		rabbitTemplate.setReturnCallback(new ReturnCallback() {
			@Override
			public void returnedMessage(Message message, int replyCode, String replyText, String exchange,
					String routingKey) {
				log.info("消息丢失:exchange({}),route({}),replyCode({}),replyText({}),message:{}", exchange, routingKey,
						replyCode, replyText, message);
			}
		});
		return rabbitTemplate;
	}
}
